/*
 * 双向循环链表
 * 参考内核代码实现
 * https://www.cnblogs.com/skywang12345/p/3562146.html
 */


#include <stdio.h>
#include <stdlib.h>



/* 参考内核代码 /usr/src/kernels/xxx/include/linux/list.h */
/******************************************************************************/

struct list_head {
    	struct list_head *next, *prev;
};



#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
        list->next = list;
        list->prev = list;
}






static inline void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
{
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
        __list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
        __list_add(new, head->prev, head);
}




#define list_for_each(pos, head) \
        for (pos = (head)->next; pos != (head); pos = pos->next)


#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)


#define container_of(ptr, type, member) ({ \
    	const typeof( ((type *)0)->member ) *__mptr = (ptr); \
    	(type *)( (char *)__mptr - offsetof(type,member) ); })


#define list_entry(ptr, type, member) \
        container_of(ptr, type, member)



/******************************************************************************/


#define NAMESIZE 32

struct student
{
	int id;
	char name[NAMESIZE];
	int gender;
	struct list_head list;
	int age;
};

void print_stu(struct student *p)
{
	printf("Stu: id = [%d], name = [%s], age = [%d]\n", p->id, p->name, p->age);
}

int main(void)
{
	int i;
	struct student *stu_ptr;
	struct list_head *cur_ptr;

	LIST_HEAD(head);

	for (i = 0; i < 10; ++i)
	{
		stu_ptr = malloc(sizeof(struct student));
		if (stu_ptr == NULL)
			return -1;

		stu_ptr->id = i;
		snprintf(stu_ptr->name, NAMESIZE, "STU_%03d", i);
		stu_ptr->gender = rand()%1;
		stu_ptr->age = rand()%100;

        /* 头插法 */
		list_add(&stu_ptr->list, &head);
	}


    /* 遍历 */
	list_for_each(cur_ptr, &head)
	{
		stu_ptr = list_entry(cur_ptr, struct student, list);
		print_stu(stu_ptr);
	}



	return 0;
}

